//------------------------------------------------------------------------------
// Copyright (c) 2008 www.dnaide.com
// Licensed under the MIT (MIT-LICENSE.txt)
//------------------------------------------------------------------------------
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Runtime.InteropServices;

namespace DNAide.Drawing
{

	/// <summary>
	/// Bitmap helper methods. Includes resizing, resizing maintain aspect ratio, save as Jpeg, save as Gif and various filters e.g. blur, sharpen, grayscale, negative, pixelate
	/// </summary>
	public static partial class BitmapAide
	{

		/// <summary>
		/// Returns a copy of an existing bitmap. The return image pixel format will be non-indexed 32bppArgb.
		/// </summary>
		/// <param name="bitmap"></param>
		/// <returns></returns>
		public static Bitmap CopyBitmap(Bitmap bitmap)
		{
			Bitmap retval = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb);
			retval.SetResolution(bitmap.HorizontalResolution, bitmap.VerticalResolution);
			using (Graphics g = Graphics.FromImage((Image)retval))
			{
				g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
			}
			return retval;
		}


		internal static bool Conv3x3(Bitmap bitmap, ConvMatrix convMatrix)
		{
			// Avoid divide by zero errors
			if (0 == convMatrix.Factor) return false;

			Bitmap bSrc = (Bitmap)bitmap.Clone();

			// GDI+ still lies to us - the return format is BGR, NOT RGB.
			BitmapData bmData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
			BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

			int stride = bmData.Stride;
			int stride2 = stride * 2;
			System.IntPtr Scan0 = bmData.Scan0;
			System.IntPtr SrcScan0 = bmSrc.Scan0;

			unsafe
			{
				byte* p = (byte*)(void*)Scan0;
				byte* pSrc = (byte*)(void*)SrcScan0;

				int nOffset = stride + 6 - bitmap.Width * 3;
				int nWidth = bitmap.Width - 2;
				int nHeight = bitmap.Height - 2;

				int nPixel;

				for (int y = 0; y < nHeight; ++y)
				{
					for (int x = 0; x < nWidth; ++x)
					{
						nPixel = ((((pSrc[2] * convMatrix.TopLeft) + (pSrc[5] * convMatrix.TopMid) + (pSrc[8] * convMatrix.TopRight) +
							(pSrc[2 + stride] * convMatrix.MidLeft) + (pSrc[5 + stride] * convMatrix.Pixel) + (pSrc[8 + stride] * convMatrix.MidRight) +
							(pSrc[2 + stride2] * convMatrix.BottomLeft) + (pSrc[5 + stride2] * convMatrix.BottomMid) + (pSrc[8 + stride2] * convMatrix.BottomRight)) / convMatrix.Factor) + convMatrix.Offset);

						if (nPixel < 0) nPixel = 0;
						if (nPixel > 255) nPixel = 255;

						p[5 + stride] = (byte)nPixel;

						nPixel = ((((pSrc[1] * convMatrix.TopLeft) + (pSrc[4] * convMatrix.TopMid) + (pSrc[7] * convMatrix.TopRight) +
							(pSrc[1 + stride] * convMatrix.MidLeft) + (pSrc[4 + stride] * convMatrix.Pixel) + (pSrc[7 + stride] * convMatrix.MidRight) +
							(pSrc[1 + stride2] * convMatrix.BottomLeft) + (pSrc[4 + stride2] * convMatrix.BottomMid) + (pSrc[7 + stride2] * convMatrix.BottomRight)) / convMatrix.Factor) + convMatrix.Offset);

						if (nPixel < 0) nPixel = 0;
						if (nPixel > 255) nPixel = 255;

						p[4 + stride] = (byte)nPixel;

						nPixel = ((((pSrc[0] * convMatrix.TopLeft) + (pSrc[3] * convMatrix.TopMid) + (pSrc[6] * convMatrix.TopRight) +
							(pSrc[0 + stride] * convMatrix.MidLeft) + (pSrc[3 + stride] * convMatrix.Pixel) + (pSrc[6 + stride] * convMatrix.MidRight) +
							(pSrc[0 + stride2] * convMatrix.BottomLeft) + (pSrc[3 + stride2] * convMatrix.BottomMid) + (pSrc[6 + stride2] * convMatrix.BottomRight)) / convMatrix.Factor) + convMatrix.Offset);

						if (nPixel < 0) nPixel = 0;
						if (nPixel > 255) nPixel = 255;

						p[3 + stride] = (byte)nPixel;

						p += 3;
						pSrc += 3;
					}

					p += nOffset;
					pSrc += nOffset;
				}
			}

			bitmap.UnlockBits(bmData);
			bSrc.UnlockBits(bmSrc);

			return true;
		}


		internal static ColorPalette SetTransparentColor(ColorPalette sourcePalette, int numberOfColors, System.Drawing.Color transparentColor)
		{
			System.Drawing.Color color;
			System.Drawing.Color[] colors = sourcePalette.Entries;
			for (int i = 0; i < colors.Length; i++) 
			{
				color = colors[i];
				if (color.R == transparentColor.R && color.G == transparentColor.G && color.B == transparentColor.B)
				{
					sourcePalette.Entries[i] = Color.FromArgb(0, color.R, color.G, color.B);
				}
				else
				{
					sourcePalette.Entries[i] = Color.FromArgb(255, color.R, color.G, color.B);
				}
			}
			return sourcePalette;
		}

	

	}
}
